package com.googlecode.marrowboy.writers;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
import java.util.Date;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.VelocityException;

import com.googlecode.marrowboy.assertionresult.TestRunDetail;
import com.googlecode.marrowboy.utilities.StringUtils;

/**
 * Implementation of {@link ReportWriter} which uses Apache Velocity template
 * library.
 * 
 * @author mjg
 */
public class VelocityTemplateWriter implements ReportWriter {

	private final CssProvider cssProvider;
	private final String templateName;

	/**
	 * Constructor. The template will be found on the classpath hopefully. If it
	 * is not, a {@link RuntimeException} will be thrown wrapping the
	 * {@link VelocityException}.
	 */
	public VelocityTemplateWriter(String templateName) {
		cssProvider = new DefaultCssProvider();
		this.templateName = templateName;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * Any exceptions thrown by Velocity are wrapped with
	 * {@link RuntimeException}s
	 */
	public void writeReport(TestRunDetail testResults, PrintStream stream) {

		VelocityEngine ve = new VelocityEngine();
		ve.setProperty("resource.loader", "class");
		ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");

		try {
			ve.init();

		} catch (Exception e) {
			throw new RuntimeException("Exception caught while initialising Velocity", e);

		}

		VelocityContext context = new VelocityContext();
		context.put("css", cssProvider.getCss());
		context.put("dateTime", new Date().toString());
		context.put("results", testResults);
		context.put("util", new StringUtils());
		context.put("newline", System.getProperty("line.separator"));

		Writer outputWriter = new OutputStreamWriter(stream);

		try {
			ve.mergeTemplate(templateName, "utf-8", context, outputWriter);

		} catch (Exception e) {
			throw new RuntimeException("Exception caught while merging Velocity", e);

		}

		try {
			outputWriter.flush();
			outputWriter.close();

		} catch (IOException e) {
			throw new RuntimeException("Exception caught while closing output stream", e);

		}

	}
}
